#include <string>
#include <unordered_set>
using namespace std;

// 滑动窗口 + 哈希表
// 思路：使用滑动窗口维护一个不含重复字符的子串，使用哈希表存储当前窗口中的字符
//    左右指针初始化都指向字符串的起始位置，右指针向右移动扩展窗口，
//       当遇到重复字符时，左指针向右移动缩小窗口，直到窗口中不含重复字符为止
class Solution
{
public:
    int lengthOfLongestSubstring(string s)
    {
        int res = 0;                                               // 结果
        int cur_window = 0;                                        // 当前窗口长度
        unordered_set<char> u_set;                                 // 存储当前窗口中的字符
        for (int left = 0, right = 0; right < s.length(); ++right) // 右指针遍历字符串
        {
            while (left < right && u_set.count(s[right])) // 当前字符已存在于窗口中，移动左指针缩小窗口
            {
                u_set.erase(s[left]);
                ++left;
                --cur_window;
            }
            // 将当前字符加入窗口
            u_set.insert(s[right]);
            ++cur_window;               // 更新当前窗口长度
            res = max(cur_window, res); // 更新结果
        }
        return res;
    }
};